package com.berwin.bmfb.views;

import com.berwin.bmfb.consts.Language;
import com.berwin.bmfb.entity.BMChar;
import com.berwin.bmfb.entity.BMFont;
import com.berwin.bmfb.utility.BMFontParser;
import com.berwin.bmfb.utility.UserDefault;
import com.berwin.bmfb.utility.Utility;
import com.berwin.bmfb.views.components.Toast;
import com.berwin.bmfb.views.dialogs.AddLetterDialog;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

public class MainView extends JFrame implements ActionListener {


    public static final String KEY_LAST_DIRECTORY = "key_last_directory";
    public static final String KEY_LAST_FILE = "key_last_file";
    private static final String KEY_LAST_SAVE_OTHER_DIR = "key_last_save_other_dir";
    private static final String KEY_LAST_OPEN_DIR = "key_last_open_dir";
    private Toast toast;

    private BMFont bmFont = null;

    private BaseConfigView baseConfigView = null;
    private CharsView charsView = null;
    private EditorView editorView = null;
    private PreviewView previewView = null;
    private AttributesView attributesView = null;

    private List<BasePanel> listBasePanel = new ArrayList<BasePanel>();

    public MainView() throws IOException {
        try {
            /**
             * 设置图形界面外观 java的图形界面外观有3种,默认是java的金属外观,还有就是windows系统,motif系统外观.
             * 1、Metal风格 (默认) UIManager.setLookAndFeel(
             * "javax.swing.plaf.metal.MetalLookAndFeel"); 2、Windows风格
             * UIManager.setLookAndFeel(
             * "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); 3、Windows
             * Classic风格 UIManager.setLookAndFeel(
             * "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel");
             * 4、Motif风格 UIManager.setLookAndFeel(
             * "com.sun.java.swing.plaf.motif.MotifLookAndFeel"); 5、Mac风格
             * (需要在相关的操作系统上方可实现) String lookAndFeel =
             * "com.sun.java.swing.plaf.mac.MacLookAndFeel"
             * ;UIManager.setLookAndFeel(lookAndFeel); 6、GTK风格 (需要在相关的操作系统上方可实现)
             * String lookAndFeel =
             * "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
             * UIManager.setLookAndFeel(lookAndFeel); 7、可跨平台的默认风格 String
             * lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
             * UIManager.setLookAndFeel(lookAndFeel); 8、当前系统的风格 String
             * lookAndFeel = UIManager.getSystemLookAndFeelClassName();
             * UIManager.setLookAndFeel(lookAndFeel);
             */
            if ("Mac OS X".equals(System.getProperties().getProperty("os.name"))) {
                UIManager
                        .setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
//                System.setProperty("apple.laf.useScreenMenuBar", "true");//设置程序的menubar显示到Mac的菜单栏上
                System.setProperty("com.apple.mrj.application.apple.menu.about.name", "BMFont工具");//设定Mac中程序运行时菜单栏显示
            } else {
                UIManager
                        .setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        this.toast = new Toast(this, "", 2000);

//        this.setTitle("BMFont Builder (1.0.0)");
        Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
        float rate = 0.75f;
        this.setSize(new Dimension((int) (dimension.getWidth() * rate), (int) (dimension.getHeight() * rate)));
        this.setLocationRelativeTo(null);
        this.setTitle(Language.TITLE);
//        this.setResizable(false);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        this.initMenuBar();

        // TODO 加载数据
        UserDefault.getInstance();
//        this.bmFont = BMFontParser.load("./res/fonts/number-export.fnt");
        this.bmFont = new BMFont();

        // LAYOUT
        this.setLayout(new BorderLayout());

        // WEST
        JPanel west = new JPanel(new GridLayout(2, 1));
        this.add(west, BorderLayout.WEST);

        // 左上
        JPanel fontConfig = Utility.makeBorderPanel("字体配置");
        fontConfig.setLayout(new BorderLayout());
        west.add(fontConfig);
        this.baseConfigView = new BaseConfigView(this, this.bmFont);
        fontConfig.add(this.baseConfigView);
        // 左下
        this.charsView = new CharsView(this, this.bmFont);
        JPanel charsContainer = Utility.makeBorderPanel("字体字符");
        charsContainer.setLayout(new BorderLayout());
        charsContainer.add(this.charsView);
        west.add(charsContainer);

        // CENTER
        JPanel center = new JPanel(new BorderLayout());
        this.add(center, BorderLayout.CENTER);

        // 中上
        this.editorView = new EditorView(this, this.bmFont);
        JPanel textureEditorContainer = Utility.makeBorderPanel("字符图集");
        textureEditorContainer.setLayout(new BorderLayout());
        textureEditorContainer.add(this.editorView);
        center.add(textureEditorContainer, BorderLayout.CENTER);
        // 中下
        this.previewView = new PreviewView(this, this.bmFont);
        JPanel previewContainer = Utility.makeBorderPanel("预览");
        previewContainer.setLayout(new BorderLayout());
        previewContainer.add(this.previewView);
        center.add(previewContainer, BorderLayout.SOUTH);


        // EAST
        JPanel east = Utility.makeBorderPanel("字符属性");
        this.attributesView = new AttributesView(this, this.bmFont);
        east.add(this.attributesView);
        this.add(east, BorderLayout.EAST);

        listBasePanel.add(this.attributesView);
        listBasePanel.add(this.baseConfigView);
        listBasePanel.add(this.charsView);
        listBasePanel.add(this.editorView);
        listBasePanel.add(this.previewView);

        this.handleLetterSelected(0);

        new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, new DropTargetAdapter() {
            @Override
            public void drop(DropTargetDropEvent dtde) {
                MainView.this.drop(dtde);
            }
        });
    }

    private void initMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        this.setJMenuBar(menuBar);

        JMenu fileMenu = new JMenu("文件");
        menuBar.add(fileMenu);

        JMenuItem newMenuItem = new JMenuItem("新建");
        newMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.META_MASK));
        newMenuItem.addActionListener(this);
        fileMenu.add(newMenuItem);
        fileMenu.addSeparator();

        JMenuItem openMenuItem = new JMenuItem("打开");
        openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.META_MASK));
        openMenuItem.addActionListener(this);
        fileMenu.add(openMenuItem);

        JMenuItem saveMenuItem = new JMenuItem("保存");
        saveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.META_MASK));
        saveMenuItem.addActionListener(this);
        fileMenu.add(saveMenuItem);

        JMenuItem saveOtherMenuItem = new JMenuItem("另存为");
        saveOtherMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.META_MASK | ActionEvent.SHIFT_MASK));
        saveOtherMenuItem.addActionListener(this);
        fileMenu.add(saveOtherMenuItem);
        fileMenu.addSeparator();

        JMenuItem exitMenuItem = new JMenuItem("退出");
        exitMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.META_MASK));
        exitMenuItem.addActionListener(this);
        fileMenu.add(exitMenuItem);

        // 关于
        JMenu menuAbout = new JMenu("关于");
        menuBar.add(menuAbout);

        JMenuItem linkAbout = new JMenuItem("开源地址");
        linkAbout.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L, ActionEvent.META_MASK));
        linkAbout.addActionListener(this);
        menuAbout.add(linkAbout);
        menuAbout.addSeparator();

        JMenuItem itemAbout = new JMenuItem("关于");
        itemAbout.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.META_MASK));
        itemAbout.addActionListener(this);
        menuAbout.add(itemAbout);
    }


    public void handleLetterSelected(int idx) {
        if (this.attributesView == null)
            return;
        for (int i = 0; i < listBasePanel.size(); i++) {
            BasePanel panel = listBasePanel.get(i);
            panel.onSelectLetter(idx);
        }
    }


    public void handleUpdate() {
        if (this.attributesView == null)
            return;
        for (int i = 0; i < listBasePanel.size(); i++) {
            BasePanel panel = listBasePanel.get(i);
            panel.onUpdate();
        }
    }

    /**
     * 刷新图片界面的位置调整，需要跳转的情况如下
     * 1.有新的字符加入
     * 2.有字符被删除
     */
    public void handleDoLayoutChars() {
        for (int i = 0; i < listBasePanel.size(); i++) {
            BasePanel panel = listBasePanel.get(i);
            panel.doLayoutChars();
        }
    }

    public void handleBMFontUpdated(BMFont bmFont) {
        for (int i = 0; i < listBasePanel.size(); i++) {
            BasePanel panel = listBasePanel.get(i);
            panel.onBMFontUpdated(bmFont);
        }
    }


    public void drop(DropTargetDropEvent dtde) {
        try {
            if (dtde.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                // 接收拖拽来的数据
                dtde.acceptDrop(DnDConstants.ACTION_COPY_OR_MOVE);
                List<File> list = (List<File>) (dtde.getTransferable()
                        .getTransferData(DataFlavor.javaFileListFlavor));
                if (list.size() == 1) {
                    String fntPath = list.get(0).getAbsolutePath();
                    if (fntPath.endsWith(".fnt")) {
                        this.toast.popup("处理FNT字体", Toast.msg);
                        this.bmFont = BMFontParser.load(fntPath);
                        this.handleBMFontUpdated(this.bmFont);
                    } else if (fntPath.endsWith(".png")) {
//                        this.toast.popup("处理字体图片或碎图", Toast.msg);
                        BufferedImage bufferedImage = ImageIO.read(new File(fntPath));
                        BMChar bmChar = new BMChar();
                        bmChar.setX(0);
                        bmChar.setY(0);
                        bmChar.setWidth(bufferedImage.getWidth());
                        bmChar.setHeight(bufferedImage.getHeight());
                        bmChar.setxAdvance(bufferedImage.getWidth());
                        bmChar.setImage(bufferedImage);
                        new AddLetterDialog(this, "", bmFont, bmChar).setVisible(true);
                    }
                } else {
                    for (File file : list) {
                        if (!file.getAbsolutePath().endsWith(".png")) {
                            this.toast.popup("只支持PNG格式图片", Toast.error);
                            continue;
                        }
                        String fntPath = file.getAbsolutePath();
                        BufferedImage bufferedImage = ImageIO.read(new File(fntPath));
                        BMChar bmChar = new BMChar();
                        bmChar.setX(0);
                        bmChar.setY(0);
                        bmChar.setWidth(bufferedImage.getWidth());
                        bmChar.setHeight(bufferedImage.getHeight());
                        bmChar.setxAdvance(bufferedImage.getWidth());
                        bmChar.setImage(bufferedImage);
                        new AddLetterDialog(this, "", bmFont, bmChar).setVisible(true);
                    }
                }
                dtde.dropComplete(true);
            } else {
                this.toast.popup("文件不是fnt字体文件", Toast.error);
                dtde.rejectDrop();
            }
        } catch (UnsupportedFlavorException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Toast getToast() {
        return toast;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        JMenuItem menuItem = (JMenuItem) e.getSource();
        if (menuItem != null) {
            if (menuItem.getAccelerator().equals(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.META_MASK | ActionEvent.SHIFT_MASK))) {
                // 另存为

                JFileChooser fileChooser = new JFileChooser(UserDefault.getInstance().getValueForKey(KEY_LAST_SAVE_OTHER_DIR, this.bmFont.getFilePath()));
                fileChooser.setFileFilter(new FileFilter() {
                    @Override
                    public boolean accept(File f) {
                        return f.getAbsolutePath().endsWith(".fnt");
                    }

                    @Override
                    public String getDescription() {
                        return ".fnt格式文件";
                    }
                });
                fileChooser.setSelectedFile(new File(this.bmFont.getFace() + ".fnt"));
                int i = fileChooser.showSaveDialog(this);
                if (i == JFileChooser.APPROVE_OPTION) {
                    File selFile = fileChooser.getSelectedFile();
                    String file = selFile.getAbsolutePath();
                    if (!file.endsWith(".fnt")) {
                        file += ".fnt";
                        selFile = new File(file);
                    }
                    UserDefault.getInstance().setValueForKey(KEY_LAST_SAVE_OTHER_DIR, selFile.getParent());
                    String pngFile = selFile.getParent() + "/" + bmFont.getPageFile();
                    try {
                        BMFontParser.save(this.bmFont, file, pngFile);
                        this.toast.popup("保存成功", Toast.success);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                        this.toast.popup("保存失败", Toast.error);
                    }
                }
            } else if (menuItem.getAccelerator().equals(KeyStroke.getKeyStroke(KeyEvent.VK_S, ActionEvent.META_MASK))) {
                try {
                    if (this.bmFont.getFilePath().equals("")) {
                        this.toast.popup("请配置文件路径", Toast.error);
                        return;
                    }
                    BMFontParser.save(this.bmFont, this.bmFont.getFilePath(), this.bmFont.getPngPath());
                    this.toast.popup("保存成功", Toast.success);
                } catch (IOException ex) {
                    ex.printStackTrace();
                    this.toast.popup("保存失败", Toast.error);
                }
            } else if (menuItem.getAccelerator().equals(KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.META_MASK))) {
                // 打开选择文件
                JFileChooser fileChooser = new JFileChooser(UserDefault.getInstance().getValueForKey(KEY_LAST_OPEN_DIR, this.bmFont.getFilePath()));
                fileChooser.setFileFilter(new FileFilter() {
                    @Override
                    public boolean accept(File f) {
                        return f.getAbsolutePath().endsWith(".fnt");
                    }

                    @Override
                    public String getDescription() {
                        return ".fnt格式文件";
                    }
                });
                fileChooser.setSelectedFile(new File(this.bmFont.getFace() + ".fnt"));
                int i = fileChooser.showOpenDialog(this);
                if (i == JFileChooser.APPROVE_OPTION) {
                    File selFile = fileChooser.getSelectedFile();
                    String file = selFile.getAbsolutePath();
                    if (!file.endsWith(".fnt")) {
                        this.toast.popup("不是FNT字体文件", Toast.error);
                        return;
                    }
                    UserDefault.getInstance().setValueForKey(KEY_LAST_OPEN_DIR, file);
                    try {
                        this.bmFont = BMFontParser.load(file);
                        this.handleBMFontUpdated(this.bmFont);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                        this.toast.popup("打开失败", Toast.error);
                    }
                }

            } else if (menuItem.getAccelerator().equals(KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.META_MASK))) {
                // TODO 是否保存之前的
                this.bmFont = new BMFont();
                this.handleBMFontUpdated(this.bmFont);
            } else if (menuItem.getAccelerator().equals(KeyStroke.getKeyStroke(KeyEvent.VK_L, ActionEvent.META_MASK))) {
                String url = "https://gitee.com/berwin/BMFBuilder";
                try {
                    URI u = URI.create(url);
                    Desktop desktop = Desktop.getDesktop();
                    if (desktop.isSupported(Desktop.Action.BROWSE)) {
                        desktop.browse(u);
                    }
                } catch (MalformedURLException ex) {
                    ex.printStackTrace();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            } else if (menuItem.getAccelerator().equals(KeyStroke.getKeyStroke(KeyEvent.VK_A, ActionEvent.META_MASK))) {
                String name = "关于软件";
                String version = "1.0.0";
                String content = "BMFont生成工具\r\n@版本: 1.0.0\r\n@作者: 唐博文";
                String txt = name + "(" + version + ")" + "\r\n\r\n" + content;
                JOptionPane.showMessageDialog(MainView.this, txt, "",
                        JOptionPane.INFORMATION_MESSAGE);
            }
        }
    }
}
